
import mxgraph from "src/pages/mxgraph/graph/index";
import graphUtil from "pages/mxgraph/graphUtil";
import { behaviors } from "src/pages/mxgraph/behaviors";

const {

  mxConstants,
  mxCellState,
  mxCellEditor,
  mxGraphHandler,
  mxEvent,

  mxUtils,
  mxText,

  mxClient,

  mxRectangle,

} = mxgraph;
//// /**
////      * HTML in-place editor
////      */
//// mxCellEditor.prototype.isContentEditing = function () {
////   let state = this.graph.view.getState(this.editingCell);

////   return state != null && state.style["html"] == 1;
//// };

//// /**
////      * Returns true if all selected text is inside a table element.
////      */
//// mxCellEditor.prototype.isTableSelected = function () {
////   return (
////     this.graph.getParentByName(
////       this.graph.getSelectedElement(),
////       "TABLE",
////       this.textarea
////     ) != null
////   );
//// };

//// /**
////      * Sets the alignment of the current selected cell. This sets the
////      * alignment in the cell style, removes all alignment within the
////      * text and invokes the built-in alignment function.
////      *
////      * Only the built-in function is invoked if shift is pressed or
////      * if table cells are selected and shift is not pressed.
////      */
//// mxCellEditor.prototype.alignText = function (align, evt) {
////   if (
////     !this.isTableSelected() == (evt == null || !mxEvent.isShiftDown(evt))
////   ) {
////     this.graph.cellEditor.setAlign(align);

////     this.graph.processElements(this.textarea, function (elt) {
////       elt.removeAttribute("align");
////       elt.style.textAlign = null;
////     });
////   }

////   document.execCommand("justify" + align.toLowerCase(), false, null);
//// };

//// /**
////      * Creates the keyboard event handler for the current graph and history.
////      */
//// mxCellEditor.prototype.saveSelection = function () {
////   if (window.getSelection) {
////     let sel = window.getSelection();

////     if (sel.getRangeAt && sel.rangeCount) {
////       let ranges = [];

////       for (let i = 0, len = sel.rangeCount; i < len; ++i) {
////         ranges.push(sel.getRangeAt(i));
////       }

////       return ranges;
////     }
////   } else if (document.selection && document.selection.createRange) {
////     return document.selection.createRange();
////   }

////   return null;
//// };

//// /**
////      * Creates the keyboard event handler for the current graph and history.
////      */
//// mxCellEditor.prototype.restoreSelection = function (savedSel) {
////   try {
////     if (savedSel) {
////       if (window.getSelection) {
////         let sel = window.getSelection();
////         sel.removeAllRanges();

////         for (let i = 0, len = savedSel.length; i < len; ++i) {
////           sel.addRange(savedSel[i]);
////         }
////       } else if (document.selection && savedSel.select) {
////         savedSel.select();
////       }
////     }
////   } catch (e) {
////     //// ignore
////   }
//// };
//// /**
////      * HTML in-place editor
////      */
//// mxCellEditor.prototype.escapeCancelsEditing = false;

//// let mxCellEditorStartEditing = mxCellEditor.prototype.startEditing;
//// mxCellEditor.prototype.startEditing = function (cell, trigger) {
////   console.log('startEditing');
////   mxCellEditorStartEditing.apply(this, arguments);

////   //// Overrides class in case of HTML content to add
////   //// dashed borders for divs and table cells
////   let state = this.graph.view.getState(cell);

////   if (state != null && state.style["html"] == 1) {
////     this.textarea.className = "mxCellEditor geContentEditable";
////   } else {
////     this.textarea.className = "mxCellEditor mxPlainTextEditor";
////   }

////   //// Toggles markup vs wysiwyg mode
////   this.codeViewMode = false;

////   //// Stores current selection range when switching between markup and code
////   this.switchSelectionState = null;

////   //// Selects editing cell
////   this.graph.setSelectionCell(cell);

////   //// Enables focus outline for edges and edge labels
////   let parent = this.graph.getModel().getParent(cell);
////   let geo = this.graph.getCellGeometry(cell);

////   if (
////     (this.graph.getModel().isEdge(parent) && geo != null && geo.relative) ||
////         this.graph.getModel().isEdge(cell)
////   ) {
////     //// Quirks does not support outline at all so use border instead
////     if (mxClient.IS_QUIRKS) {
////       this.textarea.style.border = "gray dotted 1px";
////     }
////     //// IE>8 and FF on Windows uses outline default of none
////     else if (
////       mxClient.IS_IE ||
////           mxClient.IS_IE11 ||
////           (mxClient.IS_FF && mxClient.IS_WIN)
////     ) {
////       this.textarea.style.outline = "gray dotted 1px";
////     } else {
////       this.textarea.style.outline = "";
////     }
////   } else if (mxClient.IS_QUIRKS) {
////     this.textarea.style.outline = "none";
////     this.textarea.style.border = "";
////   }
//// };

//// /**
////      * HTML in-place editor
////      */
//// let cellEditorInstallListeners = mxCellEditor.prototype.installListeners;
//// mxCellEditor.prototype.installListeners = function (elt) {
////   cellEditorInstallListeners.apply(this, arguments);

////   //// Adds a reference from the clone to the original node, recursively
////   function reference(node, clone) {
////     clone.originalNode = node;

////     node = node.firstChild;
////     let child = clone.firstChild;

////     while (node != null && child != null) {
////       reference(node, child);
////       node = node.nextSibling;
////       child = child.nextSibling;
////     }

////     return clone;
////   }

////   //// Checks the given node for new nodes, recursively
////   function checkNode(node, clone) {
////     if (node != null) {
////       if (clone.originalNode != node) {
////         cleanNode(node);
////       } else {
////         node = node.firstChild;
////         clone = clone.firstChild;

////         while (node != null) {
////           let nextNode = node.nextSibling;

////           if (clone == null) {
////             cleanNode(node);
////           } else {
////             checkNode(node, clone);
////             clone = clone.nextSibling;
////           }

////           node = nextNode;
////         }
////       }
////     }
////   }

////   //// Removes unused DOM nodes and attributes, recursively
////   function cleanNode(node) {
////     let child = node.firstChild;

////     while (child != null) {
////       let next = child.nextSibling;
////       cleanNode(child);
////       child = next;
////     }

////     if (
////       (node.nodeType != 1 ||
////             (node.nodeName !== "BR" && node.firstChild == null)) &&
////           (node.nodeType != 3 ||
////             mxUtils.trim(mxUtils.getTextContent(node)).length == 0)
////     ) {
////       node.parentNode.removeChild(node);
////     } else {
////       //// Removes linefeeds
////       if (node.nodeType == 3) {
////         mxUtils.setTextContent(
////           node,
////           mxUtils.getTextContent(node).replace(/\n|\r/g, "")
////         );
////       }

////       //// Removes CSS classes and styles (for Word and Excel)
////       if (node.nodeType == 1) {
////         node.removeAttribute("style");
////         node.removeAttribute("class");
////         node.removeAttribute("width");
////         node.removeAttribute("cellpadding");
////         node.removeAttribute("cellspacing");
////         node.removeAttribute("border");
////       }
////     }
////   }

////   //// Handles paste from Word, Excel etc by removing styles, classnames and unused nodes
////   //// LATER: Fix undo/redo for paste
////   if (
////     !mxClient.IS_QUIRKS &&
////         document.documentMode !== 7 &&
////         document.documentMode !== 8
////   ) {
////     mxEvent.addListener(
////       this.textarea,
////       "paste",
////       mxUtils.bind(this, function (evt) {
////         let clone = reference(this.textarea, this.textarea.cloneNode(true));

////         window.setTimeout(
////           mxUtils.bind(this, function () {
////             //// Paste from Word or Excel
////             if (
////               this.textarea != null &&
////                   (this.textarea.innerHTML.indexOf(
////                     "<o:OfficeDocumentSettings>"
////                   ) >= 0 ||
////                     this.textarea.innerHTML.indexOf("<!--[if !mso]>") >= 0)
////             ) {
////               checkNode(this.textarea, clone);
////             }
////           }),
////           0
////         );
////       })
////     );
////   }
//// };

//// mxCellEditor.prototype.toggleViewMode = function () {
////   let state = this.graph.view.getState(this.editingCell);

////   if (state != null) {
////     let nl2Br =
////           state != null && mxUtils.getValue(state.style, "nl2Br", "1") != "0";
////     let tmp = this.saveSelection();

////     if (!this.codeViewMode) {
////       //// Clears the initial empty label on the first keystroke
////       if (
////         this.clearOnChange &&
////             this.textarea.innerHTML == this.getEmptyLabelText()
////       ) {
////         this.clearOnChange = false;
////         this.textarea.innerHTML = "";
////       }

////       //// Removes newlines from HTML and converts breaks to newlines
////       //// to match the HTML output in plain text
////       let content = mxUtils.htmlEntities(this.textarea.innerHTML);

////       //// Workaround for trailing line breaks being ignored in the editor
////       if (!mxClient.IS_QUIRKS && document.documentMode != 8) {
////         content = mxUtils.replaceTrailingNewlines(
////           content,
////           "<div><br></div>"
////         );
////       }

////       content = this.graph.sanitizeHtml(
////         nl2Br
////           ? content.replace(/\n/g, "").replace(/&lt;br\s*.?&gt;/g, "<br>")
////           : content,
////         true
////       );
////       this.textarea.className = "mxCellEditor mxPlainTextEditor";

////       let size = mxConstants.DEFAULT_FONTSIZE;

////       this.textarea.style.lineHeight = mxConstants.ABSOLUTE_LINE_HEIGHT
////         ? Math.round(size * mxConstants.LINE_HEIGHT) + "px"
////         : mxConstants.LINE_HEIGHT;
////       this.textarea.style.fontSize = Math.round(size) + "px";
////       this.textarea.style.textDecoration = "";
////       this.textarea.style.fontWeight = "normal";
////       this.textarea.style.fontStyle = "";
////       this.textarea.style.fontFamily = mxConstants.DEFAULT_FONTFAMILY;
////       this.textarea.style.textAlign = "left";

////       //// Adds padding to make cursor visible with borders
////       this.textarea.style.padding = "2px";

////       if (this.textarea.innerHTML != content) {
////         this.textarea.innerHTML = content;
////       }

////       this.codeViewMode = true;
////     } else {
////       let content = mxUtils.extractTextWithWhitespace(
////         this.textarea.childNodes
////       );

////       //// Strips trailing line break
////       if (
////         content.length > 0 &&
////             content.charAt(content.length - 1) == "\n"
////       ) {
////         content = content.substring(0, content.length - 1);
////       }

////       content = this.graph.sanitizeHtml(
////         nl2Br ? content.replace(/\n/g, "<br/>") : content,
////         true
////       );
////       this.textarea.className = "mxCellEditor geContentEditable";

////       let size = mxUtils.getValue(
////         state.style,
////         mxConstants.STYLE_FONTSIZE,
////         mxConstants.DEFAULT_FONTSIZE
////       );
////       let family = mxUtils.getValue(
////         state.style,
////         mxConstants.STYLE_FONTFAMILY,
////         mxConstants.DEFAULT_FONTFAMILY
////       );
////       let align = mxUtils.getValue(
////         state.style,
////         mxConstants.STYLE_ALIGN,
////         mxConstants.ALIGN_LEFT
////       );
////       let bold =
////             (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
////               mxConstants.FONT_BOLD) ==
////             mxConstants.FONT_BOLD;
////       let italic =
////             (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
////               mxConstants.FONT_ITALIC) ==
////             mxConstants.FONT_ITALIC;
////       let uline =
////             (mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0) &
////               mxConstants.FONT_UNDERLINE) ==
////             mxConstants.FONT_UNDERLINE;

////       this.textarea.style.lineHeight = mxConstants.ABSOLUTE_LINE_HEIGHT
////         ? Math.round(size * mxConstants.LINE_HEIGHT) + "px"
////         : mxConstants.LINE_HEIGHT;
////       this.textarea.style.fontSize = Math.round(size) + "px";
////       this.textarea.style.textDecoration = uline ? "underline" : "";
////       this.textarea.style.fontWeight = bold ? "bold" : "normal";
////       this.textarea.style.fontStyle = italic ? "italic" : "";
////       this.textarea.style.fontFamily = family;
////       this.textarea.style.textAlign = align;
////       this.textarea.style.padding = "0px";

////       if (this.textarea.innerHTML != content) {
////         this.textarea.innerHTML = content;

////         if (this.textarea.innerHTML.length == 0) {
////           this.textarea.innerHTML = this.getEmptyLabelText();
////           this.clearOnChange = this.textarea.innerHTML.length > 0;
////         }
////       }

////       this.codeViewMode = false;
////     }

////     this.textarea.focus();

////     if (this.switchSelectionState != null) {
////       this.restoreSelection(this.switchSelectionState);
////     }

////     this.switchSelectionState = tmp;
////     this.resize();
////   }
//// };
/**
 * Function: resize
 *
 * Returns <modified>.
 */
//// const resize = mxCellEditor.prototype.resize;

//// 先提交数据到模型，提交成功后再继续原有的逻辑
mxCellEditor.prototype.applyValue = function(state, value)
{
  const cell = state.cell;
  const diagram = this.graph.diagram;
  let res;
  const behavior = this.graph.behaviors.get(state.cell.umlShape.getTypeName());
  behavior.rename(state.cell.umlShape, value, this.graph.diagramNode);
  //// if (cell.parent.edge || lifelineUtil.isMessageEdge({ typeName: cell.typeName })) {
  ////   //// 更新message时，需要加上之前的序号
  ////   if (lifelineUtil.isMessageEdge({ typeName: cell.typeName })){
  ////     let reg = /(\d+)(:+)/g;
  ////     let old = cell.value;
  ////     if (!reg.test(value)){
  ////       value = old.slice(0, old.indexOf(':')) + ":" + value;
  ////     }
  ////   }
  ////   res = graphUtil.post('/graph/edge/update', {
  ////     typeName: cell.typeName,
  ////     edgeShape: cell.parent.umlShape,
  ////     diagram,
  ////     option: { name: value }
  ////   });

  //// } else {
  ////   res = graphUtil.post('/graph/shape/update', {
  ////     oldShape: cell.umlShape,
  ////     text: value,
  ////     typeName: cell.typeName,
  ////     diagram
  ////   });

  //// }
  //// if (res.status === -1) {
  ////   window.app.tipError(res.error);

  ////   return;
  ////   //// cell.setValue(old);
  ////   //// throw res.error;
  //// }

  this.graph.labelChanged(state.cell, value, this.trigger, this.textarea.getBoundingClientRect());
  app.$bus.emit('fresh-graph');
};

//// 原计算的left少了4px,这里就是为了给left加上4px的偏移
mxCellEditor.prototype.resize = function(){
  console.log("resize");
  let state = this.graph.getView().getState(this.editingCell);

  if (state == null)
  {
    this.stopEditing(true);
  }
  else if (this.textarea != null)
  {
    let isEdge = this.graph.getModel().isEdge(state.cell);
    let scale = this.graph.getView().scale;
    let m = null;

    if (!this.autoSize || (state.style[mxConstants.STYLE_OVERFLOW] == 'fill'))
    {
      //// Specifies the bounds of the editor box
      this.bounds = this.getEditorBounds(state);
      this.textarea.style.width = Math.round(this.bounds.width / scale) + 'px';
      this.textarea.style.height = Math.round(this.bounds.height / scale) + 'px';

      //// FIXME: Offset when scaled
      if (document.documentMode == 8 || mxClient.IS_QUIRKS)
      {
        this.textarea.style.left = Math.round(this.bounds.x) + 'px';
        this.textarea.style.top = Math.round(this.bounds.y) + 'px';
      }
      else
      {
        this.textarea.style.left = Math.max(0, Math.round(this.bounds.x + 1)) + 'px';
        this.textarea.style.top = Math.max(0, Math.round(this.bounds.y + 1)) + 'px';
      }

      //// Installs native word wrapping and avoids word wrap for empty label placeholder
      if (this.graph.isWrapping(state.cell) && (this.bounds.width >= 2 || this.bounds.height >= 2) &&
        this.textarea.innerHTML != this.getEmptyLabelText())
      {
        this.textarea.style.wordWrap = mxConstants.WORD_WRAP;
        this.textarea.style.whiteSpace = 'normal';

        if (state.style[mxConstants.STYLE_OVERFLOW] != 'fill')
        {
          this.textarea.style.width = Math.round(this.bounds.width / scale) + this.wordWrapPadding + 'px';
        }
      }
      else
      {
        this.textarea.style.whiteSpace = 'nowrap';

        if (state.style[mxConstants.STYLE_OVERFLOW] != 'fill')
        {
          this.textarea.style.width = '';
        }
      }
    }
    else
    {
      let lw = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_WIDTH, null);
      m = (state.text != null && this.align == null) ? state.text.margin : null;

      if (m == null)
      {
        m = mxUtils.getAlignmentAsPoint(this.align || mxUtils.getValue(state.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER),
          mxUtils.getValue(state.style, mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE));
      }

      if (isEdge)
      {
        this.bounds = new mxRectangle(state.absoluteOffset.x, state.absoluteOffset.y, 0, 0);

        if (lw != null)
        {
          let tmp = (parseFloat(lw) + 2) * scale;
          this.bounds.width = tmp;
          this.bounds.x += m.x * tmp;
        }
      }
      else
      {
        let bds = mxRectangle.fromRectangle(state);
        let hpos = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);
        let vpos = mxUtils.getValue(state.style, mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE);

        bds = (state.shape != null && hpos == mxConstants.ALIGN_CENTER && vpos == mxConstants.ALIGN_MIDDLE) ? state.shape.getLabelBounds(bds) : bds;

        if (lw != null)
        {
          bds.width = parseFloat(lw) * scale;
        }

        if (!state.view.graph.cellRenderer.legacySpacing || state.style[mxConstants.STYLE_OVERFLOW] !== 'width')
        {
          let spacing = parseInt(state.style[mxConstants.STYLE_SPACING] || 2) * scale;
          let spacingTop = (parseInt(state.style[mxConstants.STYLE_SPACING_TOP] || 0) + mxText.prototype.baseSpacingTop) * scale + spacing;
          let spacingRight = (parseInt(state.style[mxConstants.STYLE_SPACING_RIGHT] || 0) + mxText.prototype.baseSpacingRight) * scale + spacing;
          let spacingBottom = (parseInt(state.style[mxConstants.STYLE_SPACING_BOTTOM] || 0) + mxText.prototype.baseSpacingBottom) * scale + spacing;
          let spacingLeft = (parseInt(state.style[mxConstants.STYLE_SPACING_LEFT] || 0) + mxText.prototype.baseSpacingLeft) * scale + spacing;

          let hpos = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER);
          let vpos = mxUtils.getValue(state.style, mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE);

          bds = new mxRectangle(bds.x + spacingLeft, bds.y + spacingTop,
            bds.width - ((hpos == mxConstants.ALIGN_CENTER && lw == null) ? (spacingLeft + spacingRight) : 0),
            bds.height - ((vpos == mxConstants.ALIGN_MIDDLE) ? (spacingTop + spacingBottom) : 0));
        }

        this.bounds = new mxRectangle(bds.x + state.absoluteOffset.x, bds.y + state.absoluteOffset.y, bds.width, bds.height);
      }

      //// Needed for word wrap inside text blocks with oversize lines to match the final result where
      //// the width of the longest line is used as the reference for text alignment in the cell
      //// TODO: Fix word wrapping preview for edge labels in helloworld.html
      if (this.graph.isWrapping(state.cell) && (this.bounds.width >= 2 || this.bounds.height >= 2) &&
        this.textarea.innerHTML != this.getEmptyLabelText())
      {
        this.textarea.style.wordWrap = mxConstants.WORD_WRAP;
        this.textarea.style.whiteSpace = 'normal';

        //// Forces automatic reflow if text is removed from an oversize label and normal word wrap
        let tmp = Math.round(this.bounds.width / ((document.documentMode == 8) ? scale : scale)) + this.wordWrapPadding;

        if (this.textarea.style.position != 'relative')
        {
          this.textarea.style.width = tmp + 'px';

          if (this.textarea.scrollWidth > tmp)
          {
            this.textarea.style.width = this.textarea.scrollWidth + 'px';
          }
        }
        else
        {

          this.textarea.style.maxWidth = tmp + 'px';
          this.textarea.style.width = tmp + 'px'; //// 设定宽度
        }
      }
      else
      {
        //// KNOWN: Trailing cursor in IE9 quirks mode is not visible
        this.textarea.style.whiteSpace = 'nowrap';
        this.textarea.style.width = '';
      }

      //// LATER: Keep in visible area, add fine tuning for pixel precision
      //// Workaround for wrong measuring in IE8 standards
      if (document.documentMode == 8)
      {
        this.textarea.style.zoom = '1';
        this.textarea.style.height = 'auto';
      }

      let ow = this.textarea.scrollWidth;
      let oh = this.textarea.scrollHeight;

      //// TODO: Update CSS width and height if smaller than minResize or remove minResize
      //// if (this.minResize != null)
      //// {
      ////  ow = Math.max(ow, this.minResize.width);
      ////  oh = Math.max(oh, this.minResize.height);
      //// }

      //// LATER: Keep in visible area, add fine tuning for pixel precision
      if (document.documentMode == 8)
      {
        //// LATER: Scaled wrapping and position is wrong in IE8
        this.textarea.style.left = Math.max(0, Math.ceil((this.bounds.x - m.x * (this.bounds.width - (ow + 1) * scale) + ow * (scale - 1) * 0 + (m.x + 0.5) * 2) / scale)) + 'px';
        this.textarea.style.top = Math.max(0, Math.ceil((this.bounds.y - m.y * (this.bounds.height - (oh + 0.5) * scale) + oh * (scale - 1) * 0 + Math.abs(m.y + 0.5) * 1) / scale)) + 'px';
        //// Workaround for wrong event handling width and height
        this.textarea.style.width = Math.round(ow * scale) + 'px';
        this.textarea.style.height = Math.round(oh * scale) + 'px';
      }
      else if (mxClient.IS_QUIRKS)
      {
        this.textarea.style.left = Math.max(0, Math.ceil(this.bounds.x - m.x * (this.bounds.width - (ow + 1) * scale) + ow * (scale - 1) * 0 + (m.x + 0.5) * 2)) + 'px';
        this.textarea.style.top = Math.max(0, Math.ceil(this.bounds.y - m.y * (this.bounds.height - (oh + 0.5) * scale) + oh * (scale - 1) * 0 + Math.abs(m.y + 0.5) * 1)) + 'px';
      }
      else
      {
        //// 只是改了left 增加了4
        this.textarea.style.left = Math.max(0, Math.round(this.bounds.x - m.x * (this.bounds.width - 2)) + 5) + 'px';
        this.textarea.style.top = Math.max(0, Math.round(this.bounds.y - m.y * (this.bounds.height - 4) + ((m.y == -1) ? 3 : 0)) + 1) + 'px';
      }
    }

    if (mxClient.IS_VML)
    {
      this.textarea.style.zoom = scale;
    }
    else
    {
      mxUtils.setPrefixedStyle(this.textarea.style, 'transformOrigin', '0px 0px');
      mxUtils.setPrefixedStyle(this.textarea.style, 'transform',
        'scale(' + scale + ',' + scale + ')' + ((m == null) ? '' :
          ' translate(' + (m.x * 100) + '%,' + (m.y * 100) + '%)'));
    }
  }
};

//// let mxCellEditorResize = mxCellEditor.prototype.resize;
//// mxCellEditor.prototype.resize = function (state, trigger) {
////   if (this.textarea != null) {
////     let state = this.graph.getView().getState(this.editingCell);

////     if (this.codeViewMode && state != null) {
////       let scale = state.view.scale;
////       this.bounds = mxRectangle.fromRectangle(state);

////       //// General placement of code editor if cell has no size
////       //// LATER: Fix HTML editor bounds for edge labels
////       if (this.bounds.width == 0 && this.bounds.height == 0) {
////         this.bounds.width = 160 * scale;
////         this.bounds.height = 60 * scale;

////         let m = state.text != null ? state.text.margin : null;

////         if (m == null) {
////           m = mxUtils.getAlignmentAsPoint(
////             mxUtils.getValue(
////               state.style,
////               mxConstants.STYLE_ALIGN,
////               mxConstants.ALIGN_CENTER
////             ),
////             mxUtils.getValue(
////               state.style,
////               mxConstants.STYLE_VERTICAL_ALIGN,
////               mxConstants.ALIGN_MIDDLE
////             )
////           );
////         }

////         this.bounds.x += m.x * this.bounds.width;
////         this.bounds.y += m.y * this.bounds.height;
////       }

////       this.textarea.style.width =
////             Math.round((this.bounds.width - 4) / scale) + "px";
////       this.textarea.style.height =
////             Math.round((this.bounds.height - 4) / scale) + "px";
////       this.textarea.style.overflow = "auto";

////       //// Adds scrollbar offset if visible
////       if (this.textarea.clientHeight < this.textarea.offsetHeight) {
////         this.textarea.style.height =
////               Math.round(this.bounds.height / scale) +
////               (this.textarea.offsetHeight - this.textarea.clientHeight) +
////               "px";
////         this.bounds.height = parseInt(this.textarea.style.height) * scale;
////       }

////       if (this.textarea.clientWidth < this.textarea.offsetWidth) {
////         this.textarea.style.width =
////               Math.round(this.bounds.width / scale) +
////               (this.textarea.offsetWidth - this.textarea.clientWidth) +
////               "px";
////         this.bounds.width = parseInt(this.textarea.style.width) * scale;
////       }

////       this.textarea.style.left = Math.round(this.bounds.x) + "px";
////       this.textarea.style.top = Math.round(this.bounds.y) + "px";

////       if (mxClient.IS_VML) {
////         this.textarea.style.zoom = scale;
////       } else {
////         mxUtils.setPrefixedStyle(
////           this.textarea.style,
////           "transform",
////           "scale(" + scale + "," + scale + ")"
////         );
////       }
////     } else {
////       this.textarea.style.height = "";
////       this.textarea.style.overflow = "";
////       mxCellEditorResize.apply(this, arguments);
////     }
////   }
//// };

//// let mxCellEditorGetInitialValue = mxCellEditor.prototype.getInitialValue;
//// mxCellEditor.prototype.getInitialValue = function (state, trigger) {
////   return state.cell.umlShape.container.title;
////   if (mxUtils.getValue(state.style, "html", "0") == "0") {
////     return mxCellEditorGetInitialValue.apply(this, arguments);
////   } else {
////     let result = this.graph.getEditingValue(state.cell, trigger);

////     if (mxUtils.getValue(state.style, "nl2Br", "1") == "1") {
////       result = result.replace(/\n/g, "<br/>");
////     }

////     result = this.graph.sanitizeHtml(result, true);

////     return result;
////   }
//// };

//// let mxCellEditorGetCurrentValue = mxCellEditor.prototype.getCurrentValue;
//// mxCellEditor.prototype.getCurrentValue = function (state) {
////   if (mxUtils.getValue(state.style, "html", "0") == "0") {
////     return mxCellEditorGetCurrentValue.apply(this, arguments);
////   } else {
////     let result = this.graph.sanitizeHtml(this.textarea.innerHTML, true);

////     if (mxUtils.getValue(state.style, "nl2Br", "1") == "1") {
////       result = result.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>");
////     } else {
////       result = result.replace(/\r\n/g, "").replace(/\n/g, "");
////     }

////     return result;
////   }
//// };

//// let mxCellEditorStopEditing = mxCellEditor.prototype.stopEditing;
//// mxCellEditor.prototype.stopEditing = function (cancel) {
////   //// Restores default view mode before applying value
////   if (this.codeViewMode) {
////     this.toggleViewMode();
////   }

////   mxCellEditorStopEditing.apply(this, arguments);

////   //// Tries to move focus back to container after editing if possible
////   this.focusContainer();
//// };

//// mxCellEditor.prototype.focusContainer = function () {
////   try {
////     this.graph.container.focus();
////   } catch (e) {
////     //// ignore
////   }
//// };

//// let mxCellEditorApplyValue = mxCellEditor.prototype.applyValue;
//// mxCellEditor.prototype.applyValue = function (state, value) {
////   //// Removes empty relative child labels in edges
////   this.graph.getModel().beginUpdate();

////   try {
////     mxCellEditorApplyValue.apply(this, arguments);

////     if (
////       this.graph.isCellDeletable(state.cell) &&
////           this.graph.model.getChildCount(state.cell) == 0
////     ) {
////       let stroke = mxUtils.getValue(
////         state.style,
////         mxConstants.STYLE_STROKECOLOR,
////         mxConstants.NONE
////       );
////       let fill = mxUtils.getValue(
////         state.style,
////         mxConstants.STYLE_FILLCOLOR,
////         mxConstants.NONE
////       );

////       if (
////         value == "" &&
////             stroke == mxConstants.NONE &&
////             fill == mxConstants.NONE
////       ) {
////         this.graph.removeCells([state.cell], false);
////       }
////     }
////   } finally {
////     this.graph.getModel().endUpdate();
////   }
//// };

//// /**
////      * Returns the background color to be used for the editing box. This returns
////      * the label background for edge labels and null for all other cases.
////      */
//// mxCellEditor.prototype.getBackgroundColor = function (state) {
////   let color = mxUtils.getValue(
////     state.style,
////     mxConstants.STYLE_LABEL_BACKGROUNDCOLOR,
////     null
////   );

////   if (
////     (color == null || color == mxConstants.NONE) &&
////         state.cell.geometry != null && state.cell.geometry.width > 0 &&
////         (mxUtils.getValue(state.style, mxConstants.STYLE_ROTATION, 0) != 0 ||
////           mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0)
////   ) {
////     color = mxUtils.getValue(
////       state.style,
////       mxConstants.STYLE_FILLCOLOR,
////       null
////     );
////   }

////   if (color == mxConstants.NONE) {
////     color = null;
////   }

////   return color;
//// };

//// mxCellEditor.prototype.getMinimumSize = function (state) {
////   let scale = this.graph.getView().scale;

////   return new mxRectangle(
////     0,
////     0,
////     state.text == null ? 30 : state.text.size * scale + 20,
////     30
////   );
//// };
